package com.top.up.aspect;

import com.alibaba.fastjson.JSONObject;
import com.top.up.annotation.LogInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Objects;

@Slf4j
@Aspect
@Configuration
@Order(Integer.MAX_VALUE -1)
class LogInfoAspect {

    @Pointcut("@annotation(com.top.up.annotation.LogInfo)")
    public void deCut(){}

    @Around("deCut()")
    public Object println(ProceedingJoinPoint point) throws Throwable{
        long beginTime = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        LogInfo annotation = method.getAnnotation(LogInfo.class);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        request.setAttribute("beginTime", beginTime);
        request.setAttribute("methodName", method.getName());

        log.info("<===============【请求信息开始】===============>");
        log.info("请求URL:{}", request.getRequestURL().toString());
        log.info("请求方法:{}", method.getName());
        log.info("请求方式:{}", request.getMethod());
        log.info("请求描述:{}", Objects.isNull(annotation) ? "未定义描述" : annotation.description());
        log.info("请求IP:{}", getIpAddress(request));
        log.info("请求参数:{}", JSONObject.toJSONString(point.getArgs()));
        log.info("<===============【请求信息结束】===============>");

        Object[] args = point.getArgs();

        Object result = point.proceed(args);
        long endTime = System.currentTimeMillis();

        if (Objects.nonNull(annotation) && annotation.out()) {
            log.info("请求URL:{},耗时：【{}】ms，响应结果：【{}】", request.getRequestURL().toString(), endTime - beginTime, JSONObject.toJSONString(result));
        } else {
            log.info("请求URL:{},耗时：【{}】ms", request.getRequestURL().toString(), endTime - beginTime);
        }

        return result;
    }

    private String getIpAddress(HttpServletRequest request) {
        String[] headers = {"x-forwarded-for", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};

        for (String header : headers) {
            String ip = request.getHeader(header);
            if (Objects.nonNull(ip) && !"unknown".equalsIgnoreCase(ip)) {
                return ip;
            }
        }
        return request.getRemoteAddr();
    }
}
